/*
Javier Kohen's Java Framework Classes.
Copyright (C) 2000  Javier Kohen <jkohen at tough.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package ar.com.jkohen.awt;

import java.awt.*;
import java.awt.event.*;

import ar.com.jkohen.util.Resources;

public class ImageButton extends Canvas implements MouseListener, MouseMotionListener
{
	public final static int NORMAL = 0;
    public final static int PRESSED = 1;
    public final static int DISABLED = 2;
    public final static int ALERT = 3;
	
    public final static int STATES = 4;

    private ActionListener actionListener;

	Graphics gr;
	Image image;

    private Image stateImages[];
    private String text;
    private Image icon;
	private int shift;
	private int button_width = 0, button_height = 0;
	private int leftBorder = 3, topBorder = 3;
	private boolean pos_icon = true;

    private FontMetrics fm;
    private int baseline;
    private int text_height = 0, text_width = 0, text_base = 0;

    protected String action_command;

    protected int state = NORMAL;

    protected boolean mouseOver = false;
    protected boolean mousePressed = false;

    public ImageButton()
    {
    	setButtonType(true);
    }
    
    public ImageButton(boolean b)
    {
    	setButtonType(b);
    }

    public ImageButton(String t)
    {
    	setButtonType(true);
    	setText(t);
    }
    
    public ImageButton(String t, Image i)
    {
    	setButtonType(true);    	
    	setText(t);
    	setIcon(i);
    }
    
    public void setButtonType(boolean b)
    {
    	this.stateImages = new Image[STATES];
    	this.action_command = "";

    	addMouseListener(this);
    	addMouseMotionListener(this);
    	
    	if (b)
    	{
    		setImage(NORMAL, Resources.LARGE_NORMAL);
    		setImage(PRESSED, Resources.LARGE_PRESSED);
    		setImage(DISABLED, Resources.LARGE_DISABLED);
    		setImage(ALERT, Resources.LARGE_ALERT);
    	}
    	else
    	{
    		setImage(NORMAL, Resources.SMALL_NORMAL);
    		setImage(PRESSED, Resources.SMALL_PRESSED);
    		setImage(DISABLED, Resources.SMALL_DISABLED);
    	}
    }
    
    public void setImage(int st, Image i)
    {
		this.stateImages[st] = i;
    }

    public void setIcon(Image i)
    {
		this.icon = i;
    }
    
    public void setText(String t)
    {
		this.text = t;
		fm = null;
    }

    public void setIconPosition(boolean b)
    {
		this.pos_icon = b;
    }
	
	public void setWaitType()
	{
		setImage(DISABLED, Resources.LARGE_WAIT);
	}
	
	private void createImageBuffer(Dimension size)
	{
		image = createImage(size.width, size.height);
		if (gr != null)
			gr.dispose();

		gr = image.getGraphics();
    }
	
    public void update(Graphics g)
	{
		paint(g);
    }
	
	public void paint(Graphics g)
    {
		paintButton();
		paintText();
		g.drawImage(image, 0, 0, this);
	}

	public void paintButton()
    {
		Dimension size = getSize();
		if (gr == null || size.height != image.getHeight(this) || size.width != image.getWidth(this))
	    	createImageBuffer(size);
			
		if (!isEnabled())
		    this.state = DISABLED;

		if (stateImages[state] != null)
		{
	    	gr.setColor(getBackground());
	    	gr.fillRect(0, 0, getSize().width, getSize().height);

			if (pos_icon || icon == null)
			    gr.drawImage(stateImages[state], 0, 0, this);
			else
			    gr.drawImage(stateImages[state], icon.getWidth(this), 0, this);

		    button_width = stateImages[state].getWidth(this);
		    button_height = stateImages[state].getHeight(this);
		}
		    
		shift = 0;
		if (state == DISABLED || state == PRESSED)
			shift = 1;
		    
   		if (icon != null)
		{
			if (pos_icon)
				gr.drawImage(icon, leftBorder + shift, topBorder + shift, this);
			else
				gr.drawImage(icon, 0, 0, this);
		}
		
	}
	
	public void paintText()
	{
		if (gr == null) return;

		gr.setColor(Color.black);
		if (mouseOver)
			gr.setColor(Color.blue);
		if (state == DISABLED)
			gr.setColor(Color.gray);
			
		if (text != null)
		{
			fm = gr.getFontMetrics();
    		text_height = fm.getMaxAscent() + fm.getMaxDescent() + fm.getLeading();
   		 	text_width = fm.stringWidth(text);
	    	text_base = fm.getMaxAscent() + fm.getLeading();
	    	
			if (icon != null)
 				gr.drawString(text, (button_width - text_width - icon.getWidth(this)) / 2 + shift + icon.getWidth(this), (button_height - text_height - topBorder * 2) / 2 + text_base + topBorder + shift);
			else
 				gr.drawString(text, (button_width - text_width) / 2 + shift, (button_height - text_height - topBorder * 2) / 2 + text_base + topBorder + shift);
		}
		
	}
	
    public void mouseMoved(MouseEvent e)
	{
		setCursor(new Cursor(Cursor.HAND_CURSOR));

		this.mouseOver = true;
		if (state == PRESSED)
		    return;
			
		this.state = mousePressed ? PRESSED : NORMAL;
		
		repaint();
    }
    
    public void mouseDragged(MouseEvent e)
	{
	}

    public void mouseClicked(MouseEvent e)
    {
    }
    	
    public void mouseEntered(MouseEvent e)
	{
	}

    public void mouseExited(MouseEvent e)
	{
		setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

		this.mouseOver = false;
		this.state = NORMAL;
		
		repaint();
    }

    public void mousePressed(MouseEvent e)
	{
		this.mousePressed = true;
		this.state = PRESSED;
  		repaint();
    }

    public void mouseReleased(MouseEvent e)
	{
		this.mousePressed = false;
		this.state = NORMAL;
		repaint();
		processActionEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, action_command, e.getModifiers()));
    }

    public Dimension getPreferredSize()
    {
		int w = -1, h = -1;
		w = stateImages[state].getWidth(this);
		h = stateImages[state].getHeight(this);
		
		if (!pos_icon && icon != null)
			w += icon.getWidth(this);
		
		return(new Dimension(w, h));
    }

    public Dimension getMinimumSize()
    {
		return(getPreferredSize());
    }

    public void setEnabled(boolean active)
    {
		if (isEnabled() != active)
		{
		    this.state = NORMAL;
		    this.mouseOver = false;
		    super.setEnabled(active);
   		    repaint();
		}
    }

	public void setFont(Font f)
	{
		if (gr != null)
			gr.setFont(f);
		repaint();
	}
	
    public void addActionListener(ActionListener l)
    {
		if (null != l)
		    actionListener = AWTEventMulticaster.add(actionListener, l);
    }

    public void removeActionListener(ActionListener l)
    {
		if (null != l)
		    actionListener = AWTEventMulticaster.remove(actionListener, l);
    }

    public String getActionCommand()
    {
		return action_command;
    }

    public void setActionCommand(String action)
    {
		this.action_command = action;
    }

    protected void processActionEvent(ActionEvent e)
    {
		if (actionListener != null)
		    actionListener.actionPerformed(e);
    }
}
